package demo.aspect;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.mongodb.core.query.Query;

import com.alibaba.fastjson.JSONObject;

/**
 * 拦截器，过滤设备数据根据_id范围取值，create_at 和_id 时间不对应的情况 将create_at 不在_id时间范围内的记录过滤掉
 * 
 * @author xufeng
 *
 */
@Aspect
public class MongoTemplateFilterAspect {

    private static Logger logger = LoggerFactory.getLogger(MongoTemplateFilterAspect.class);

    private String appName;

    private static final String DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS";
    private static final String GT = "$gt";
    private static final String GTE = "$gte";
    private static final String LT = "$lt";
    private static final String LTE = "$lte";

    @Pointcut("execution(java.util.List org.springframework.data.mongodb.core.MongoTemplate.find(..))")
    // @Pointcut("execution(* org.springframework.data.mongodb.core.MongoTemplate.*(..))")
    public void myMongoTemplatePoint() {
        logger.info("myMongoTemplatePoint");
        // 方法体留空
    }

    @Around(value = "myMongoTemplatePoint()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        long begin = System.currentTimeMillis();
        Object result = null;
        Object[] args = null;

        try {
            args = pjp.getArgs();
            result = pjp.proceed(args);
            Query query = (Query) args[0];
            // 必须是find方法,返回值是list而且是设备相关的数据且查询条件是根据_id范围查找的情况，进入数据过滤逻辑
            if (!isDeviceData(args)) {
                return result;
            }
            List<Object> list = (List) result;
            if (list == null || list.isEmpty()) {
                return result;
            }
            Object objId = query.getQueryObject().get("_id");
            Map<String, Object> m = (Map<String, Object>) objId;
            Date startDate = null;
            Date endDate = null;
            Object startId = null;
            Object endId = null;
            String operator1 = "";
            String operator2 = "";
            if (m.containsKey(GT)) {
                operator1 = GT;
                startId = m.get(GT);
            } else if (m.containsKey(GTE)) {
                operator1 = GTE;
                startId = m.get(GTE);
            }
            if (m.containsKey(LT)) {
                operator2 = LT;
                endId = m.get(LT);
            } else if (m.containsKey(LTE)) {
                operator2 = LTE;
                endId = m.get(LTE);
            }
            if (startId != null && startId.toString().length() > 8) {
                startDate = new Date(Long.parseLong(startId.toString().substring(0, 8), 16) * 1000);
            }
            if (endId != null && endId.toString().length() > 8) {
                endDate = new Date(Long.parseLong(endId.toString().substring(0, 8), 16) * 1000);
            }
            List<Object> removeList = new ArrayList<>(1);
            for (Object t : list) {
                Date createAt = getCreateAt(t);
                if (isRemoveT(startDate, createAt, operator1) || isRemoveT(endDate, createAt, operator2)) {
                    removeList.add(t);
                }

            }
            list.removeAll(removeList);
            return result;
        } catch (Exception e) {
            logger.error("MongoTemplateFilterAspect run traceAspect error", e);
        } finally {
            long cost = System.currentTimeMillis() - begin;
            String beginTime = DateFormatUtils.format(begin, DATE_TIME_FORMAT);
            // 得到执行的方法
            String method = pjp.getSignature().getName();
            logger.info("{} {} {} {} ", appName, method, beginTime, cost);
        }
        return result;
    }

    private boolean isDeviceData(Object[] args) {
        if (args == null || args.length < 2) {
            return false;
        }
        Query query = (Query) args[0];
        Object objId = query.getQueryObject().get("_id");
        if (objId == null || !(objId instanceof Map)) {
            return false;
        }

        Object obj = args[1];
        logger.info("{}", obj.getClass());
        return true;

    }

    private Date getCreateAt(Object t) {

        Date date = new Date();
        String json = JSONObject.toJSONString(t);
        logger.info("{}", json);
        return date;

    }

    /**
     * date1 查询条件开始或者结束时间，date2 抓取时间
     * 
     * @param date1
     * @param date2
     * @param operator
     * @return
     */
    private boolean isRemoveT(Date date1, Date date2, String operator) {

        if (date1 == null || date2 == null) {
            return false;
        }
        boolean isRemove = false;
        int compareValue = date1.compareTo(date2);
        switch (operator) {
        case GT:
            isRemove = compareValue >= 0;
            break;
        case GTE:
            isRemove = compareValue > 0;
            break;
        case LT:
            isRemove = compareValue <= 0;
            break;
        case LTE:
            isRemove = compareValue < 0;
            break;
        default:
            break;
        }

        return isRemove;
    }

    public String getAppName() {
        return appName;
    }

    public void setAppName(String appName) {
        this.appName = appName;
    }

}
